#region Namespace References

using System;
using System.Collections;
using System.Collections.Generic;
using DynConDevCorp.OpenArch.SmartData.Interfaces;
using DynConDevCorp.OpenArch.SmartData.Interfaces.Attributes;
using DynConDevCorp.OpenArch.SmartData.Interfaces.EventArgClasses;
using DynConDevCorp.OpenArch.SmartData.Core.Metadata;

#endregion

namespace DynConDevCorp.OpenArch.SmartData.Core
{
    public abstract class SmartEntityCollection : SmartEntity, ISmartEntityCollection
    {

        #region ISmartEntityCollection Members

        void ISmartEntityCollection.Add(ISmartEntity entity)
        {
            throw new NotImplementedException();
        }

        public abstract void Clear();
        public event EventHandler<CollectionChangedEventArgs> CollectionChanged;

        IEnumerable<TReturn> ISmartEntityCollection.GetEntities<TReturn>()
        {
            throw new NotImplementedException();
        }

        TReturn ISmartEntityCollection.GetEntity<TReturn>(int index)
        {
            throw new NotImplementedException();
        }

        TReturn ISmartEntityCollection.GetEntity<TReturn>(Guid identity)
        {
            throw new NotImplementedException();
        }

        IEnumerator IEnumerable.GetEnumerator()
        {
            throw new NotImplementedException();
        }

        TReturn ISmartFieldCollection.GetFieldItem<TReturn>(int index)
        {
            throw new NotImplementedException();
        }

        IEnumerable<TReturn> ISmartFieldCollection.GetFieldItems<TReturn>()
        {
            throw new NotImplementedException();
        }

        public abstract IEnumerable<TReturn> GetItems<TReturn>() where TReturn : class, ISmartBase;

        ISmartEntity ISmartEntityCollection.NewEntity(Guid identity)
        {
            throw new NotImplementedException();
        }

        ISmartEntity ISmartEntityCollection.NewEntity()
        {
            throw new NotImplementedException();
        }

        IEnumerator ISmartEntityCollection.RawEnumerator()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Public Instance Properties

        public abstract CollectionClassCategory CollectionClassCategory { get; }

        [AutoField]
        [Persist(IsXmlPersistable = false, IsDatabaseField = false)]
        public ISmartField<int> Count { get; protected set; }

        public abstract Type ItemType { get; }

        #endregion

        #region Public Instance Methods

        public override string ToString()
        {
            ISmartEntityCollection iec = this;
            return String.Format("Count:{0} EntityType:{1}", iec.Count.Value, iec.EntityType.Name);
        }

        #endregion

        #region Private Instance Properties

        Type ISmartEntityCollection.EntityType
        {
            get { throw new NotImplementedException(); }
        }

        #endregion
    }

    /// <summary>
    /// 
    /// </summary>
    /// <typeparam name="TEntity">The type of the NTIT y_ TYPE.</typeparam>
    public class SmartEntityCollection<TEntity> : SmartEntityCollection, ISmartEntityCollection<TEntity>
        where TEntity : ISmartEntity, new()
    {
        public SmartEntityCollection()
        {
            //Console.WriteLine("Created Collection Instancce: {0}", typeof(TEntity).Name);
            SmartMetaEntity.Verbose = false;
        }

        static SmartEntityCollection()
        {
            //Console.WriteLine("Static Collection: {0}", typeof(TEntity).Name);
            SmartMetaEntity.Verbose = true;
        }


        #region ISmartEntityCollection<TEntity> Members

        /// <summary>
        /// Adds the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void Add(TEntity entity)
        {
            m_Items.Add(entity.EntityID, entity);
            UpdateCount();
        }

        /// <summary>
        /// Adds the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        public void Add(ISmartEntity entity)
        {
            TEntity typedEntity = (TEntity) entity;
            Add(typedEntity);
        }

        /// <summary>
        /// Clears this instance.
        /// </summary>
        public override void Clear()
        {
            m_Items.Clear();
        }

        /// <summary>
        /// Commits this instance.
        /// </summary>
        public override void Commit()
        {
            foreach (TEntity entity in m_Items.Values)
                entity.Commit();
            base.Commit();
        }

        /// <summary>
        /// Determines whether [contains] [the specified entity].
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <returns>
        /// 	<c>true</c> if [contains] [the specified entity]; otherwise, <c>false</c>.
        /// </returns>
        public bool Contains(TEntity entity)
        {
            return m_Items.ContainsValue(entity);
        }

        public bool Contains(Guid entityID)
        {
            return m_Items.ContainsKey(entityID);
        }

        public TEntity CreateNewEntity()
        {
            return new TEntity();
        }

        public override void Dispatch(ISmartDispatcher dispatcher, object context)
        {
            dispatcher.ProcessDispatch(this, context);
        }

        /// <summary>
        /// Occurs when [display value changed].
        /// </summary>
        public override event EventHandler<DisplayValueChangedEventArgs> DisplayValueChanged;

        /// <summary>
        /// Enables the track changes.
        /// </summary>
        /// <param name="state">if set to <c>true</c> [state].</param>
        public override void EnableTrackChanges(bool state)
        {
            foreach (TEntity entity in m_Items.Values)
                entity.EnableTrackChanges(state);
            base.EnableTrackChanges(state);
        }

        /// <summary>
        /// Formatteds the display.
        /// </summary>
        /// <param name="format">The format.</param>
        /// <returns></returns>
        public override string FormattedDisplay(string format)
        {
            throw new NotSupportedException();
        }

        /// <summary>
        /// Gets the entities.
        /// </summary>
        /// <returns></returns>
        public IEnumerable<TEntity> GetEntities()
        {
            return m_Items.Values;
        }

        /// <summary>
        /// Gets the entities.
        /// </summary>
        /// <typeparam name="TReturn">The type of the ETUR n_ ENTIT y_ TYPE.</typeparam>
        /// <returns></returns>
        public IEnumerable<TReturn> GetEntities<TReturn>() where TReturn : ISmartEntity
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the entity.
        /// </summary>
        /// <param name="entityID">The entity ID.</param>
        /// <returns></returns>
        public TEntity GetEntity(Guid entityID)
        {
            return m_Items[entityID];
        }

        /// <summary>
        /// Gets the entity.
        /// </summary>
        /// <param name="index">The index.</param>
        /// <returns></returns>
        public TEntity GetEntity(int index)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the entity.
        /// </summary>
        /// <typeparam name="TReturn">The type of the ETUR n_ ENTIT y_ TYPE.</typeparam>
        /// <param name="identity">The identity.</param>
        /// <returns></returns>
        public TReturn GetEntity<TReturn>(Guid identity) where TReturn : ISmartEntity
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the entity.
        /// </summary>
        /// <typeparam name="TReturn">The type of the ETUR n_ ENTIT y_ TYPE.</typeparam>
        /// <param name="index">The index.</param>
        /// <returns></returns>
        public TReturn GetEntity<TReturn>(int index) where TReturn : ISmartEntity
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Returns an enumerator that iterates through a collection.
        /// </summary>
        /// <returns>
        /// An <see cref="T:System.Collections.IEnumerator"/> object that can be used to iterate through the collection.
        /// </returns>
        public IEnumerator GetEnumerator()
        {
            return m_Items.Values.GetEnumerator();
        }

        /// <summary>
        /// Gets the field item.
        /// </summary>
        /// <typeparam name="TReturn">The type of the ETUR n_ TYPE.</typeparam>
        /// <param name="index">The index.</param>
        /// <returns></returns>
        public TReturn GetFieldItem<TReturn>(int index) where TReturn : ISmartField
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the field items.
        /// </summary>
        /// <typeparam name="TReturn">The type of the ETUR n_ TYPE.</typeparam>
        /// <returns></returns>
        public IEnumerable<TReturn> GetFieldItems<TReturn>() where TReturn : ISmartField
        {
            throw new NotImplementedException();
        }

        public override IEnumerable<TReturn> GetItems<TReturn>()
        {
            throw new NotImplementedException();
        }


        /// <summary>
        /// Marks as dirty.
        /// </summary>
        public override void MarkAsDirty()
        {
            foreach (TEntity entity in m_Items.Values)
                entity.MarkAsDirty();
            base.MarkAsDirty();
        }

        /// <summary>
        /// News the entity.
        /// </summary>
        /// <returns></returns>
        public ISmartEntity NewEntity()
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// News the entity.
        /// </summary>
        /// <param name="identity">The identity.</param>
        /// <returns></returns>
        public ISmartEntity NewEntity(Guid identity)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Gets the raw enumerator.
        /// </summary>
        /// <returns></returns>
        public IEnumerator RawEnumerator()
        {
            return m_Items.Values.GetEnumerator();
        }

        /// <summary>
        /// Occurs when [raw value changed].
        /// </summary>
        public override event EventHandler<ValueChangedEventArgs<object>> RawValueChanged;

        public TEntity ReCreateEntity(Guid entityID)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Removes the specified entity.
        /// </summary>
        /// <param name="entity">The entity.</param>
        /// <returns></returns>
        public bool Remove(TEntity entity)
        {
            bool retVal = m_Items.Remove(entity.EntityID);
            UpdateCount();
            return retVal;
        }

        /// <summary>
        /// Rollback value to last Committed Value.
        /// </summary>
        public override void Rollback()
        {
            foreach (TEntity entity in m_Items.Values)
                entity.Rollback();
            base.Rollback();
        }

        /// <summary>
        /// Tries the get value.
        /// </summary>
        /// <param name="id">The id.</param>
        /// <param name="value">The value.</param>
        /// <returns></returns>
        public bool TryGetValue(Guid id, out TEntity value)
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Public Instance Properties

        /// <summary>
        /// Gets the collection class.
        /// </summary>
        /// <value>The collection class.</value>
        public override CollectionClassCategory CollectionClassCategory
        {
            get { return CollectionClassCategory.Entity; }
        }


        /// <summary>
        /// Gets the type of the data.
        /// </summary>
        /// <value>The type of the data.</value>
        public override Type DataType
        {
            get { return typeof (TEntity); }
        }


        /// <summary>
        /// Gets the type of the entity.
        /// </summary>
        /// <value>The type of the entity.</value>
        public Type EntityType
        {
            get { return typeof (TEntity); }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [input inhibited].
        /// </summary>
        /// <value><c>true</c> if [input inhibited]; otherwise, <c>false</c>.</value>
        public override PartialBoolean InputInhibited
        {
            get { throw new NotImplementedException(); }
            set
            {
                foreach (TEntity entity in m_Items.Values)
                    entity.InputInhibited = value;
                base.InputInhibited = value;
            }
        }

        /// <summary>
        /// Gets a value indicating whether this instance is dirty.
        /// </summary>
        /// <value><c>true</c> if this instance is dirty; otherwise, <c>false</c>.</value>
        public override PartialBoolean IsDirty
        {
            get { throw new NotImplementedException(); }
        }

 
        /// <summary>
        /// Gets the type of the item.
        /// </summary>
        /// <value>The type of the item.</value>
        public override Type ItemType
        {
            get { return typeof (TEntity); }
        }

        /// <summary>
        /// Gets or sets the state of the persistance.
        /// </summary>
        /// <value>The state of the persistance.</value>
        public override SmartPersistenceState PersistenceState
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Gets or sets the raw value.
        /// </summary>
        /// <value>The raw value.</value>
        public override object RawValue
        {
            get { throw new NotSupportedException(); }
            set { throw new NotSupportedException(); }
        }

        /// <summary>
        /// Gets a value indicating whether [track changes].
        /// </summary>
        /// <value><c>true</c> if [track changes]; otherwise, <c>false</c>.</value>
        public override PartialBoolean TrackingChanges
        {
            get { throw new NotImplementedException(); }
        }

        /// <summary>
        /// Gets or sets a value indicating whether [read only].
        /// </summary>
        /// <value><c>true</c> if [read only]; otherwise, <c>false</c>.</value>
        public override PartialBoolean WriteLocked
        {
            get { throw new NotImplementedException(); }
            set
            {
                foreach (TEntity entity in m_Items.Values)
                    entity.WriteLocked = value;
                base.WriteLocked = value;
            }
        }

        #endregion

        #region Private Instance Methods

        private void UpdateCount()
        {
            Count.Value = m_Items.Count;
        }

        #endregion

        #region Fields and Constants

        private readonly Dictionary<Guid,TEntity> m_Items = new Dictionary<Guid,TEntity>();

        #endregion
    }
}